(module duple (lib "eopl.ss" "eopl")
  (provide duple)
;;1.14
;; duple: Number * Number -> List
;; usage: (duple n x)
;; produces: return a list containing n copies of x

;; examples:
;; (duple 2 3) ==> (3 3)
;; (duple 2 '(1 2)) ==> ((1 2) (1 2))
;; (duple 0 3) ==> ()



(define (duple n x)
  (cond
  ( (zero? n) '() )
  (else (cons x (duple (- n 1) x)))
 ))



(duple 2 3)
(duple 2 '(1 2))
(duple 0 3)
) 

;;----------------------------------------------------------------
(module swapper (lib "eopl.ss" "eopl")
  (provide swapper)
  
;;1.17
;;swapper: s1 s2 slist ==> slist
;;usage: (swapper s1 s2 slist)
;;produces: Given 2 symbols,  and a list, this procedure produces another list with the symbols swapped in the result

;;examples:
;;(swapper 'a 'd '(a b c d) ==> (d b c a)
;;(swapper 'a 'd '(a d () c d)) ==> (d a () c a)
;;(swapper 'x 'y '((x) y (z (x)))) ==> ((y) x (z (y)))

(define swapper
  (lambda (s1 s2 slist)
    (cond 
      ((null? slist) ())
      ((list? (car slist)) (cons (swapper s1 s2 (car slist)) (swapper s1 s2 (cdr slist))))
      ((eq? s1 (car slist)) (cons s2 (swapper s1 s2 (cdr slist))))
      ((eq? s2 (car slist))(cons s1 (swapper s1 s2 (cdr slist))))
      (else (cons (car slist) (swapper s1 s2 (cdr slist))))
      )
    )
  )

;;Tests
(swapper 'a 'd '(a d b c))
(swapper 'a 'd '(a b c d))
(swapper 'a 'd '(a d () c d))
(swapper 'x 'y '((x) y (z (x))))

)
;;-----------------------------------------------------------------

(module count-occurrences (lib "eopl.ss" "eopl")
  (provide count-occurrences)
;;1.18
;; count-occurrences: Symbol * List -> Number
;; usage: (count-occurrences s slist)
;; produces: return the number of occurces of s in slist

;; examples:
;; (count-occurrences 'x '((f x))) ==> 1
;; (count-occurrences 'x '((f x) y (((x z) () x)))) ==> 3
;; (count-occurrences 'w '((f x) y (((x z) x)))) ==> 0

 

(define (count-occurrences s slist)
  (cond
    ( (null? slist) 0)
    ( (pair? (car slist) ) (+ (count-occurrences s (car slist)) (count-occurrences s (cdr slist))))
    ( (eq? (car slist) s) (+ 1 (count-occurrences s (cdr slist))))
    ( else  (count-occurrences s (cdr slist)))
   )
)

 

(count-occurrences 'x '((f x)))
(count-occurrences 'x '((f x) y (((x z) () x))))
(count-occurrences 'w '((f x) y (((x z) x))))

)
;;-----------------------------------------------------------------

(module product (lib "eopl.ss" "eopl")
  (provide product)
  
;;1.20
;;product: sos1 sos2 ==> list
;;usage: (product sos1 sos2)
;;produces: Given 2 lists of symbols each of which have no repetions,  this procedure returns the list of 2-lists which is a cartesian product of the two lists. 

;;examples: 
;;(product '(a b c) '(x y))

(define product 
  (lambda (sos1 sos2)
    (cond 
      ((null? sos1) ()) 
      ((null? sos2) ())
      (else (append (prod-help (car sos1) sos2) (product (cdr sos1) sos2)))
      )
    )
  )
   

;;prod-help: s sos ==> 2-list    
;;usage: (prod-help s sos)
;;produces: Given a symbol and a list of symbols ,  this produces a list with 2-lists , with first  value being the symbl and the second value being the symb in the list.

;;examples:
;;(prod-help 'a '(x y z)) ==> ((a x) (a y) (a z))
(define prod-help
  (lambda (s sos)
    (cond 
      ((null? sos) ())
      (else (cons (list s (car sos)) (prod-help s (cdr sos))))
      )
    )
  )
 )
(product '(a b c) '(x y))

;;-----------------------------------------------------------------
(module filter-in (lib "eopl.ss" "eopl")
  (provide filter-in)
;;1.21
;;filter-in: pred lst ==> list
;;usage (filter-in pred lst)
;;produces: 

;;examples
;;(filter-in number? '(a 2 (1 3) b 7)) ==> (2 7)
;;(filter-in symbol? '(a (b c) 17 foo)) ==> (a foo)

(define filter-in
  (lambda (pred lst)
    (cond 
      ( (null? lst) ())
      ((pred (car lst)) (cons (car lst) (filter-in pred (cdr lst))))
      (else (filter-in pred (cdr lst)))
      )
    )
  )
)

;;-----------------------------------------------------------------
(module list-index (lib "eopl.ss" "eopl")
  (provide list-index)
  
;;1.22
;; list-index: Symbol * List -> Number / Boolean
;; usage: (list-index pred lst)
;; produces: return the 0-based position of the first element of lst that satisfies the predicate pred. If no element of lst satisfies the ;; ;;    predicate, then list-index returns #f

;; examples:
;; (list-index number? '(a b 1 2)) ==> 2
;; (list-index symbol? '(a b 1 2)) ==> 0
;; (list-index symbol? '(12 (a c) 5) ) ==> #f


(define (list-index pred lst)
  (cond
    ((null? lst) #f)
    ((not (pred (car lst))) (list-help pred (cdr lst) 0))
    (else 0)
   )
  )

 

(define (list-help pred lst n)
 (cond
  ((null? lst) #f)
  ((not (pred (car lst))) (list-help pred (cdr lst) (+ 1 n)))
  (else (+ n 1))
  )
 )

 

(list-index number? '(a b 1 2))
(list-index symbol? '(a b 1 2))
(list-index symbol? '(12 (a c) 5) )

)


;;-----------------------------------------------------------------

(module every (lib "eopl.ss" "eopl")
  (provide every?)
  
;; 1.23
;;every?: pred lst ==> #f or #t
;;usage: (every? pred lst)
;;produces:

;;examples:
;;(every? number? '(a b c 3 e)) ==> #f
;;(every? number? '(1 2 3 4 5)) ==> #t

(define every? 
  (lambda (pred lst)
    (cond 
      ((null? lst) #f)
      (else (pred-help #t pred lst))
      )
    )
  )

;;examples:
;;(pred-help #t number? '(1 2 3 4)) ==> #t
;; (pred-help #t number? '(1 2 b  4)) ==>#f
(define pred-help
  (lambda (bool pred list)
    (cond
      ((null? list) bool)
      ((pred (car list)) (pred-help bool pred (cdr list)))
      (else #f)
      )
    )
  )
  
;;Tests
(every? number? '(a 1 3 5))
(every? symbol? '(a f d))

)      
;;---------------------------------------------------------------------------------

(module flatten (lib "eopl.ss" "eopl")
  (provide flatten)
;;1.26  
;;flatten: slist ==> list
;;usage: (flatten slist)
;;
;;examples:
;;(flatten '(a b c)) ==> (a b c)
;;(flatten '((a) () ((b) ()) () (c))) ==> (a b c)
;;(flatten '((a b) c (((d)) e))) ==> (a b c d e)
;;(flatten '(a b (() (c) ))) ==> (a b c)

(define flatten 
  (lambda (lst)
    (cond
      ((null? lst) ())
      ((list? (car lst)) (append (flatten (car lst)) (flatten (cdr lst))))
      (else (cons (car lst) (flatten (cdr lst))))
      )
    )
  )

(flatten '(a b c))
(flatten '((a) () ((b) ()) () (c))) 
(flatten '((a b) c (((d)) e)))
(flatten '(a b (() (c) )))
)
;;-----------------------------------------------------------------
(module merge (lib "eopl.ss" "eopl")
  (provide merge)
  
;;1.27
;; merge: List * List -> List
;; usage: (merge loi1 loi2)
;; produces: return a sorted list of all the integers in loi1 and loi2

;; examples:
;; (merge '(1 4) '(1 2 8)) ==> (1 1 2 4 8)
;; (merge '(35 62 81 90 91) '(3 83 85 90)) ==> (3 35 62 81 83 85 90 90 91)

 

(define (merge loi1 loi2)
  (cond
    ((null? loi1) loi2)
    ((null? loi2) loi1)
    ((> (car loi1) (car loi2)) (cons (car loi2) (merge loi1 (cdr loi2))))
    (else (cons (car loi1) (merge loi2 (cdr loi1))));
    )
  )

 

(merge '(1 4) '(1 2 8))
(merge '(35 62 81 90 91) '(3 83 85 90))

)


